import router from '@/router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { getAccessToken } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { useDictStoreWithOut } from '@/stores/modules/dict'
import { useUserStoreWithOut } from '@/stores/modules/user'
import { usePermissionStoreWithOut } from '@/stores/modules/permission'
import { isUrl } from '@/utils/is'

const { startNProgress, doneNProgress } = useNProgress()
const { pageLoadStart, pageLoadDone } = usePageLoading()

// 不需要认证拦截的白名单
const whiteList = ['/login', '/social-login', '/auth-redirect', '/bind', '/register']

// 全局路由前置守卫
router.beforeEach(async (to, from, next) => {
  startNProgress()
  pageLoadStart()
  if (getAccessToken()) {
    if (to.path === '/login') {
      next({ path: '/index' })
    } else {
      const dictStore = useDictStoreWithOut()
      const userStore = useUserStoreWithOut()
      const permissionStore = usePermissionStoreWithOut()
      if (!dictStore.getIsDictSet) {
        try {
          isRelogin.show = true
          // 数据字典尚未获取
          await dictStore.setDictMap()
          isRelogin.show = false
        } catch (e) {
          console.log(`setDictMap err`, e)
          await userStore.logout()
          location.href = '/index'
          return
        }
      }
      if (!userStore.getIsUserSet) {
        try {
          // 获取用户、权限、授权菜单信息
          isRelogin.show = true // 强制认证失效登录提示框不要弹出
          await userStore.setUserInfo()
          isRelogin.show = false
          await permissionStore.generateRoutes()
          permissionStore.getAddRoutes.forEach((route) => {
            if (isUrl(route.path)) {
              return
            }
            router.addRoute(route as unknown as RouteRecordRaw)
          })
          const redirectPath = from.query.redirect || to.path
          // 修复跳转时不带参数的问题
          const redirect = decodeURIComponent(redirectPath as string)
          const { paramsObject: query } = parseURL(redirect)
          next(to.path === redirect ? { ...to, replace: true } : { path: redirect, query })
        } catch (e) {
          console.log(`setUserInfo err`, e)
          await userStore.logout()
          location.href = '/index'
        }
      } else {
        // 用户、权限、授权菜单信息已获取
        next()
      }
    }
  } else {
    // 无认证token
    if (whiteList.includes(to.path)) {
      // 无需认证白名单页面
      next()
    } else {
      // 未登录时访问受控页面直接跳转到登录页，带上原页面地址，登录后直接跳转到原页面
      // 当守卫中跳转到其他route时(没有next()继续深入时)，本次的afterEach不会执行，从新到新route的beforeEach流程
      next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
    }
  }
})

// 全局路由后置守卫，路由导航被确认后调用
router.afterEach((to) => {
  // 更新标题数据
  useTitle(to?.meta?.title)
  doneNProgress()
  pageLoadDone()
})

const parseURL = (
  url: string | null | undefined
): {
  basePath: string
  paramsObject: { [key: string]: string }
} => {
  // 如果输入为 null 或 undefined，返回空字符串和空对象
  if (url == null) {
    return { basePath: '', paramsObject: {} }
  }

  // 找到问号 (?) 的位置，它之前是基础路径，之后是查询参数
  const questionMarkIndex = url.indexOf('?')
  let basePath = url
  const paramsObject: { [key: string]: string } = {}

  // 如果找到了问号，说明有查询参数
  if (questionMarkIndex !== -1) {
    // 获取 basePath
    basePath = url.substring(0, questionMarkIndex)

    // 从 URL 中获取查询字符串部分
    const queryString = url.substring(questionMarkIndex + 1)

    // 使用 URLSearchParams 遍历参数
    const searchParams = new URLSearchParams(queryString)
    searchParams.forEach((value, key) => {
      // 封装进 paramsObject 对象
      paramsObject[key] = value
    })
  }

  // 返回 basePath 和 paramsObject
  return { basePath, paramsObject }
}
